// 引入类型
import type { RouterOptions, Router, App, ReactiveRoute, RouteLocationNormalized } from './types'
import { createRouterMatcher } from './matcher'
import { computed, reactive, shallowRef, unref } from 'vue'
import { START_LOCATION_NORMALIZED } from './contant'
import { useCallback } from './utils'

export function createRouter(options: RouterOptions): Router {
  // 获取 history 对象
  const routerHistory = options.history

  // 创建 matcher 对象
  const matcher = createRouterMatcher(options.routes)

  // 当前路由，一开始给了一个初始值
  const currentRoute = shallowRef(START_LOCATION_NORMALIZED)

  // 导航守卫
  const beforeGuards = useCallback()
  const beforeResolveGuards = useCallback()
  const afterGuards = useCallback()

  // 之后定义了一堆方法
  function push(to: RouteLocationNormalized) {}

  // 创建 router 对象
  const router = {
    push,
    beforeEach: beforeGuards.add,
    afterEach: afterGuards.add,
    beforeResolve: beforeResolveGuards.add,

    // 这个 router 对象暴露出去，是要作为一个插件进行安装的
    install(app: App) {
      // 让 router 等于当前外层的 router 对象
      const router = this
      // 回头外部可以通过 this.$router 拿到 router 这个对象
      app.config.globalProperties.$router = router

      // 回头外部可以通过 this.$route 拿到当前的路由
      Object.defineProperty(app.config.globalProperties, '$route', {
        enumerable: true,
        get: () => unref(currentRoute)
      })

      const reactiveRoute: ReactiveRoute = {}

      // 接下来为 reactiveRoute 添加值，并且每一项值都是计算属性
      for (const key in START_LOCATION_NORMALIZED) {
        reactiveRoute[key] = computed(() => (currentRoute.value as any)[key])
      }

      // 接下来进行依赖注入
      app.provide('router', router as any)
      app.provide('route location', reactive(reactiveRoute))

      // 注册组件
      // routerlink 和 routerview

      // 如果是初始安装 router
      // 我们需要通过路由系统先进行一次跳转
      if (currentRoute.value == START_LOCATION_NORMALIZED) {
        push(routerHistory.location as any)
      }
    }
  }

  return router
}

